package oneplay.YonghongBITools.HttpClientUtils;

import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase;
import org.apache.hc.client5.http.entity.UrlEncodedFormEntity;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.NameValuePair;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.message.BasicNameValuePair;
import org.apache.hc.core5.net.URIBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class RequestInstance {
    private static final Logger logger = LoggerFactory.getLogger(RequestInstance.class);

    private final CloseableHttpClient httpClient;

    public RequestInstance(boolean ssl) {
        httpClient = HttpClientFactory.newInstance(ssl);
    }

    /**
     * Post 请求
     *
     * @param uri  请求地址
     * @param data 表单数据
     * @return String 响应结果内容
     */
    public String post(final String uri, Map<String, String> data) throws IOException {
        HttpPost httpPost = buildHttpPost(uri, data);
        return execute(httpPost);
    }

    /**
     * Post 请求
     *
     * @param uri  请求地址
     * @param data 表单数据
     * @return InputStream 响应字节流
     */
    public byte[] postForBin(final String uri, Map<String, String> data) throws IOException {
        HttpPost httpPost = buildHttpPost(uri, data);
        return download(httpPost);
    }

    private HttpPost buildHttpPost(final String uri, Map<String, String> data) {
        List<NameValuePair> nameValuePairList = new ArrayList<>();
        if (data != null) {
            for (Map.Entry<String, String> entry : data.entrySet()) {
                nameValuePairList.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
            }
        }
        HttpPost httpPost = new HttpPost(uri);
        httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
        httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairList, StandardCharsets.UTF_8));
        return httpPost;
    }

    /**
     * Get 请求
     *
     * @param uri  请求地址
     * @param data 表单数据
     * @return String 响应结果内容
     */
    public String get(final String uri, Map<String, String> data) throws URISyntaxException, IOException {
        HttpGet httpGet = new HttpGet(buildURIRequest(uri, data));
        return execute(httpGet);
    }

    private URI buildURIRequest(final String uri, Map<String, String> data) throws URISyntaxException {
        URIBuilder uriBuilder = new URIBuilder(uri);
        if (data != null) {
            for (Map.Entry<String, String> entry : data.entrySet()) {
                uriBuilder.addParameter(entry.getKey(), entry.getValue());
            }
        }
        return uriBuilder.build();
    }

    private String execute(HttpUriRequestBase uriRequest) throws IOException {
        return httpClient.execute(uriRequest, response -> {
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                return EntityUtils.toString(entity, StandardCharsets.UTF_8);
            }
            logger.error(String.format("Http Status Code : %d, %s", response.getCode(), response.getReasonPhrase()));
            return null;
        });
    }

    private byte[] download(HttpUriRequestBase uriRequest) throws IOException {
        return httpClient.execute(uriRequest, response -> {
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                return EntityUtils.toByteArray(entity);
            }
            logger.error(String.format("Http Status Code : %d, %s", response.getCode(), response.getReasonPhrase()));
            return null;
        });
    }

}
